package com.equis.architecture.service {

	import com.equis.architecture.exception.ExceptionHandler;
	
	import mx.rpc.events.FaultEvent;
	import mx.rpc.events.ResultEvent;
	import mx.rpc.remoting.mxml.RemoteObject;

	/**
	 * This dynamic object is just a proxy, every method
	 * called on it will be forwarded to the server. The
	 * doesNotUnderstand: mechanism is implemented through
	 * proxy mechanism.
	 * 
	 * WARNING: Don't use instances of this class more tha once!!!
	 */
	public class Service {

		private var _remoteObject:RemoteObject;
	    protected var _callbackFunction:Function;
	    protected var _errorCallbackFunction:Function;
	    public var callDelegate:IServiceCallDelegate = new ServiceCallDelegate();
		public var resultHandler:Function = handleResult;

		public function Service(item:RemoteObject) {
			this._remoteObject = item;
		}
	
		public function get remoteObject():RemoteObject {
			return this._remoteObject;
		}

	    public function invoke(name:String, ... parameters):* {
	    	doInvoke(name, parameters);
	    }
    
    	protected function doInvoke(name:String, parameters:Array):* {
			trace("Invoking service " + _remoteObject.destination + "." + name);
			callDelegate.doInvocation(this, name, parameters);
    	}

	    public function set concurrency(str:String):void {
			this._remoteObject.concurrency = str;
	    }
    
	    public function handleResult(event:ResultEvent):void {
	        this.invokeResultCallback(event.result);
	    }

	    protected function invokeResultCallback(result:*):void {
	        if (callbackFunction != null) {
	            callbackFunction(result);
	        }
	    }

	    protected function invokeErrorCallback(event:FaultEvent):void {
	        if (errorCallbackFunction != null) {
	            errorCallbackFunction(event);
	        } else {
	            ExceptionHandler.instance.handle(event.fault);
	        }
	    }

	    public function handleFault(event:FaultEvent):void {
			trace("Error response received for " + _remoteObject.destination + ", " + event.toString());
	        invokeErrorCallback(event);
	        // do something...
	    }

	    public function set callbackFunction(callbackFunction:Function):void {
	        this._callbackFunction = callbackFunction;
	    }

	    public function get callbackFunction():Function {
	        return this._callbackFunction;
	    }

	    public function set errorCallbackFunction(errorCallbackFunction:Function):void {
	        this._errorCallbackFunction = errorCallbackFunction;
	    }

	    public function get errorCallbackFunction():Function {
	        return this._errorCallbackFunction;
	    }
	}
}